package com.martin.lib_base.impl

import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.OnLifecycleEvent
import androidx.lifecycle.lifecycleScope
import com.martin.lib_base.utils.ReleaseUtil
import com.martin.lib_base.utils.addReleaseForKey
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.launch
import java.util.concurrent.ConcurrentHashMap

/**
 * @author：Houge
 * @date：2022/12/1
 * @desc：
 */
object FlowBus {

    // 总线map
    private val busMap = ConcurrentHashMap<Any, MutableSharedFlow<Any>>()

    // 粘性事件总线map
    private val busStickyMap = ConcurrentHashMap<Any, MutableSharedFlow<Any>>()

    /**
     * 根据Key获取事件总线
     */
    fun <T> with(key: String): MutableSharedFlow<T> {
        if (!busMap.containsKey(key)) {
            busMap[key] = MutableSharedFlow(0, 1, BufferOverflow.DROP_OLDEST)
        }
        return busMap[key] as MutableSharedFlow<T>
    }

    /**
     * 根据Key获取事件总线
     * 粘性事件需要发送及接收都使用才奏效
     */
    fun <T> withSticky(key: String): MutableSharedFlow<T> {
        if (!busStickyMap.containsKey(key)) {
            busStickyMap[key] = MutableSharedFlow(1, 1, BufferOverflow.DROP_OLDEST)
        }
        return busStickyMap[key] as MutableSharedFlow<T>
    }

}

/**
 * 观察事件
 * 自动释放,根据生命周期自动释放资源
 */
fun <T> MutableSharedFlow<T>.observe(
    lifecycleOwner: LifecycleOwner,
    action: (T) -> Unit
) {
    val that = this
    // 添加生命周期监听
    lifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver {
        // 当生命周期处于onDestroy时，移除监听,并释放资源
        override fun onDestroy(owner: LifecycleOwner) {
            lifecycleOwner.lifecycle.removeObserver(this)
            ReleaseUtil.release(that)
        }
    })
    // 接收事件
    lifecycleOwner.lifecycleScope.launch {
        collect { action(it) }
    }.addReleaseForKey(that) {
        it.cancel()
    }
}

/**
 * 观察事件
 * 半自动释放,需要手动调用[ReleaseUtil.release]释放资源
 */
@OptIn(DelicateCoroutinesApi::class)
fun <T> MutableSharedFlow<T>.observeForKey(
    key: Any,
    scope: CoroutineScope = GlobalScope,
    action: (T) -> Unit
) {
    // 接收事件
    scope.launch {
        collect { action(it) }
    }.addReleaseForKey(key) {
        it.cancel()
    }
}
